package com.wujiayu.retry.service.impl;
import com.wujiayu.retry.pojo.DeleteVideoMessage;
import com.wujiayu.retry.service.RedisService;
import com.wujiayu.retry.service.RetryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import java.time.LocalTime;

/**
 * @Description: 重试机制业务逻辑实现类
 * @Author: WuJiaYu
 * @Date: 2021/3/11 3:42 下午
 * @Version: 1.0
 */
@Service
public class RetryServiceTestImpl implements RetryService {
    @Autowired
    private RedisService redisService;

    @Override
    /**
     * @Retryable ： 注解方式标记当前方法会使用重试机里面的
     *       value： 重试的触发机制，当遇到Exception异常的时候，触发；
     * maxAttempts： 重试的次数（包括第一次调用，也就是说如果设置3次，调用一次后，如果一直失败触发重试，那么还当前方法还会调用2次）；
     *       delay：重试的延迟时间，也就是距离上一次重试方法调用的间隔，单位毫秒
     *  multiplier： delay间隔时间的倍数，也就是说，第一次重试间隔如果是2000ms，那第二次重试的时候就是2000ms 乘以这个倍数1.5，就是3000ms；
     *    maxDelay:重试次数之间的最大时间间隔,默认为0,即忽略,如果小于delay的设置,则默认为30000L；
     * @Recover，也就是用注解方式标记当期方法为回调方法，可以看到传参里面写的是 Exception e，这个是作为回调的接头暗号（重试次数用完了，还是失败，我们抛出这个Exception e通知触发这个回调方法）
     */
    @Retryable(value = Exception.class,maxAttempts = 3,backoff = @Backoff(delay = 10000,multiplier = 1.5 ))
    public int retryServiceTest(int code) throws Exception {
        System.out.println("retryServiceTest被调用,时间："+ LocalTime.now());
        if (code==0){
            // 编写删除业务逻辑
            throw new Exception("请求参数为0，出现异常");
            // throw new IllegalArgumentException("非法数据");
        }
        System.out.println("retryServiceTest被调用,情况对头了！");
        return 200;
    }

    @Recover
    public int recover(Exception e){
        // 转发到延时队列

        // 在延时队列消费完后如果还是失败则将数据存放到redis中过期时间为3天；
        String name  = "DELETE_ALIYUN_VIDEO";
        String ossId = "1";
        redisService.hSet(name,ossId,new DeleteVideoMessage(ossId,0),259200);
        DeleteVideoMessage deleteVideoMessage = (DeleteVideoMessage)redisService.hGet(name, ossId);
        System.out.println("重试次数结束后还有异常，回调方法开始执行"+deleteVideoMessage.toString());
        //可调用其余的方法
        return 400;
    }

}
